package com.bookcloud.java21.chapter10.注解获取所有注解107;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/** 注解获取所有注解107 */
public class AllAnnotationsExample {
  /**
   * 扫描指定包下的所有类
   *
   * @param basePackage
   * @return
   * @throws Exception
   */
  public static List<Class<?>> scanClasses(String basePackage) throws Exception {
    List<Class<?>> classes = new ArrayList<>();
    // 扫描指定包下的所有类
    String packagePath = basePackage.replace(".", "/");
    // 获取类加载器
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    // 获取指定包下的所有资源
    Enumeration<URL> resources = classLoader.getResources(packagePath);
    while (resources.hasMoreElements()) {
      // 获取资源
      URL resource = resources.nextElement();
      if (resource.getProtocol().equals("file")) {
        // 获取资源对应的文件
        File dir = new File(resource.toURI());
        // 扫描目录下的所有类
        scanDir(dir, basePackage, classes);
      }
    }
    return classes;
  }

  /**
   * 扫描指定目录下的所有类
   *
   * @param dir
   * @param packageName
   * @param classes
   * @throws ClassNotFoundException
   */
  private static void scanDir(File dir, String packageName, List<Class<?>> classes)
      throws ClassNotFoundException {
    if (!dir.exists()) return;
    // 遍历目录下的所有文件
    for (File file : dir.listFiles()) {
      if (file.isDirectory()) {
        // 递归扫描子目录
        scanDir(file, packageName + "." + file.getName(), classes);
      } else if (file.getName().endsWith(".class")) {
        // 加载类
        String className = packageName + "." + file.getName().replace(".class", "");
        classes.add(Class.forName(className));
      }
    }
  }

  public static void main(String[] args) {
    // 扫描的指定包
    String scanPackage = "com.bookcloud.java21.chapter10.注解获取所有注解107";
    try {
      // 扫描指定包下的所有类
      List<Class<?>> classes = scanClasses(scanPackage);
      // 遍历所有类
      for (Class<?> clazz : classes) {
        // 只获取ClassInfo注解
        if (clazz.isAnnotationPresent(ClassInfo.class)) {
          // 获取类上的所有注解
          Annotation[] annotations = clazz.getAnnotations();

          // 遍历所有注解
          for (Annotation annotation : annotations) {
            // 打印注解信息
            System.out.println("----------------------");

            // 获取注解的属性值
            ClassInfo classInfo = clazz.getAnnotation(ClassInfo.class);
            System.out.println(classInfo.author());
            System.out.println(classInfo.date());
            System.out.println(classInfo.version());
            System.out.println(classInfo.desc());
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
